const sharp = require('sharp')
const fs = require('fs')

const inputImage = 'C:\\Users\\yundee\\Desktop\\zwqend.jpg'
const targetSizeInBytes = 100 * 1024; // 目标大小，例如100KB

// 二分查找压缩图片质量以达到指定大小 , 通常不需要改变图片类型
const compressImage = async (inputImage, targetSize, minQuality = 1, maxQuality = 100,tolerance = 1, maxIterations = 100) => {
    let buffer;
    if(typeof buffer == 'string') {
        buffer = fs.readFileSync(inputImage)
    } else {
        buffer = inputImage;
    }

    for(let i = 0; i < maxIterations; i++ ) {
        const quality = parseInt((minQuality + maxQuality) / 2)
        

        try {
            const compressedBuffer = await sharp(buffer)
            .jpeg({quality}).toBuffer();
            const compressedSize = compressedBuffer.length
            console.log('quality', quality, compressedSize - targetSizeInBytes ? true : false , (compressedSize) / 1024)
           if( compressedSize < targetSizeInBytes &&  Math.abs(compressedSize - targetSize) / targetSize <= tolerance ) {
                return { buffer: compressedBuffer, size: compressedSize, quality };
            } else if (compressedSize > targetSize) {
                  maxQuality = quality;
            } else {
                minQuality = quality;
            }

        } catch (error) {
            console.error('Error during image compression:', error);
        }
        
    }


    // 如果达到最大迭代次数仍未找到满足条件的压缩质量，则返回最后一次压缩的结果
    const lastQuality = (minQuality + maxQuality) / 2;
    const lastCompressedBuffer = await sharp(buffer)
        .jpeg({ quality: lastQuality })
        .toBuffer();
    
    const lastCompressedSize = lastCompressedBuffer.length;
    
    return { buffer: lastCompressedBuffer, size: lastCompressedSize, quality: lastQuality };
}

let time = Date.now();
(async() => {
    const result = await compressImage(inputImage, targetSizeInBytes)

    // 保存压缩后的图片到文件（可选）
    fs.writeFileSync('D:\\project\\nodejs\\fyx\\tools\\image\\compressed_image1.jpg', result.buffer);
    console.log('耗时(ms)', Date.now() - time, result)
})(time,inputImage, targetSizeInBytes)

